package com.xinzhitong.www.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xinzhitong.www.enumeration.OrderType;
import com.xinzhitong.www.enumeration.PostOrderType;
import com.xinzhitong.www.exception.*;
import com.xinzhitong.www.exception.enroll.MultipleEnrollException;
import com.xinzhitong.www.exception.positionget.NoPositionException;
import com.xinzhitong.www.exception.post.*;
import com.xinzhitong.www.exception.postcondition.NoPostConditionException;
import com.xinzhitong.www.exception.postgeneral.NoPostException;
import com.xinzhitong.www.mapper.ClickMapper;
import com.xinzhitong.www.mapper.PostMapper;
import com.xinzhitong.www.mapper.TableMapper;
import com.xinzhitong.www.pojo.Post;
import com.xinzhitong.www.pojo.User;
import com.xinzhitong.www.service.PostService;
import com.xinzhitong.www.utils.FileHelper;
import com.xinzhitong.www.utils.MyPageInfo;
import com.xinzhitong.www.utils.SearchKeyUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;

/**
 * 岗位服务实现类
 * <p>
 * <<<<<<< HEAD
 *
 * @author 徐鑫 钟伟良
 * =======
 * @author 徐鑫 魏骆淳
 * >>>>>>> weiluochun
 */
@Service
@Transactional
public class PostServiceImpl implements PostService {

    @Resource
    PostMapper postMapper;

    @Resource
    TableMapper tableMapper;

    @Resource
    ClickMapper clickMapper;

    private static Map<String, String> dateHelper = new HashMap<>();
    private static String[][] indexes;
    private static String[] indexNames = new String[]{
            "companySummary",
            "salary",
            "liveAndFood",
            "postRequest",
            "employConditions",
    };
    private static String[] companySummaryIndex = new String[]{
            "picture",
            "companyName",
            "position",
            "salary"
    };
    private static String[] salaryIndex = new String[]{
            "baseSalary",
            "paySalaryDate",
            "payType",
            "salaryOtherNotice"
    };
    private static String[] liveAndFoodIndex = new String[]{
            "liveNotice",
            "foodNotice",
            "socialSecurityNotice",
            "liveFoodOtherNotice"
    };
    private static String[] postRequestIndex = new String[]{
            "jobText",
            "jobTimeNotice",
            "jobWay",
            "jobOtherNotice"
    };
    private static String[] employConditionsIndex = new String[]{
            "sexRequest",
            "ageRequest",
            "eduBackground",
            "expRequest",
            "credentialRequest",
            "employOtherNotice"
    };

    static {
        dateHelper.put("日结", "每天?点");
        dateHelper.put("月结", "每月?号");
        dateHelper.put("年结", "每年?月");

        indexes = new String[][]{
                companySummaryIndex,
                salaryIndex,
                liveAndFoodIndex,
                postRequestIndex,
                employConditionsIndex
        };
    }

    @Override
    public Map<String, Object> getPostInfo(Integer id) throws PostNotExistException {
        Map<String, Object> res = new HashMap<>();
        Map<String, Object> post = postMapper.selectPostById(id);
        if (post == null)
            throw new PostNotExistException();

        //处理年龄条件
        Integer minAgeRequest = Integer.parseInt((String) post.get("minAgeRequest"));
        Integer maxAgeRequest = Integer.parseInt((String) post.get("maxAgeRequest"));
        String ageRequest = yearDealer(minAgeRequest, maxAgeRequest);
        post.put("ageRequest", ageRequest);
        //处理经验条件
        Integer minExpRequest = Integer.parseInt((String) post.get("minExpRequest"));
        Integer maxExpRequest = Integer.parseInt((String) post.get("maxExpRequest"));
        String expRequest = yearDealer(minExpRequest, maxExpRequest);
        post.put("expRequest", expRequest);
        //处理性别条件
        Boolean sexRequest = (Boolean) post.get("sexRequest");
        if (post.get("sexRequest") == null)
            post.remove("sexRequest");
        else
            post.put("sexRequest", sexRequest ? "男" : "女");
        //处理结算方式
        String paySalaryDateString;
        int paySalaryDate = Integer.parseInt((String) post.get("paySalaryDate"));
        post.put("payType", post.get("payType") + "结");
        String payType = (String) post.get("payType");
        paySalaryDateString = dateHelper.get(payType).replace("?", Integer.toString(paySalaryDate));
        post.put("paySalaryDate", paySalaryDateString);

        //批量加入岗位内容
        for (int i = 0; i < indexes.length; i++) {
            Map<String, Object> tmp = new HashMap<>();
            for (int j = 0; j < indexes[i].length; j++)
                tmp.put(indexes[i][j], post.get(indexes[i][j]));
            res.put(indexNames[i], tmp);
        }

        //单独加入公司内容
        Map<String, Object> companySummary = new HashMap<>();
        companySummary.put("companyId", post.get("companyId"));
        companySummary.put("companyIntroduction", post.get("companyIntroduction"));
        companySummary.put("contact", post.get("contact"));
        Map<String, Object> tmp = new HashMap<>();
        tmp.put("logo", FileHelper.fileURL + post.get("logo"));
        tmp.put("companyName", post.get("companyName"));
        tmp.put("star", post.get("star"));
        tmp.put("nature", post.get("nature"));
        tmp.put("scale", post.get("scale"));
        companySummary.put("summary", tmp);
        res.put("companySummary", companySummary);
        //额外的信息
        res.put("requirePopulation", post.get("requirePopulation"));
        res.put("professionName", post.get("professionName"));
        return res;
    }

    @Override
    public void enrollThePost(Integer id) throws PostNotExistException, EnrollException {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        if (postMapper.selectPostById(id) == null)
            throw new PostNotExistException();
        if (postMapper.selectCountUserEnrollPost(user.getUsername(), id) == 1)
            throw new MultipleEnrollException();
        if (postMapper.insertUserEnrollPost(user.getUsername(), id) == 0)
            throw new BusyException();
    }

    @Override
    public MyPageInfo getPostsSatisfyTheConditionOf(
            Map<String, Object> conditions,
            String keyWord,
            PostOrderType postOrderType,
            Integer pageNo,
            Integer pageSize
    ) throws PostException {
        keyWord = SearchKeyUtil.makeKey(keyWord);

        String orderField = null;
        OrderType orderType = null;
        switch (postOrderType) {
            case NEW:
                orderField = "releaseTime";
                orderType = OrderType.DESC;
                break;
            case SALARY:
                orderField = "convert(maxSalary, decimal)";
                orderType = OrderType.DESC;
                break;
        }

        //清除缓存中的无用数据
        tableMapper.selectFieldsOfTableOrView("post_summary");
        String[] selectFields = tableMapper.selectFieldsOfTableOrView("post_summary");
        PageHelper.startPage(pageNo, pageSize);
        List<Map<String, Object>> posts = postMapper.selectPostsByConditions(
                "post_info",
                selectFields,
                keyWord,
                orderField,
                orderType,
                conditions
        );
        if (posts.size() == 0)
            throw new PostIsEmptyException();
        for (Map<String, Object> post : posts) {
            post.put("ageRequest",
                    yearDealerFault(
                            Integer.parseInt((String) post.get("minAgeRequest")),
                            Integer.parseInt((String) post.get("maxAgeRequest"))
                    )
            );
            post.put("salary",
                    salaryDealer(
                            Double.parseDouble((String) post.get("minSalary")),
                            Double.parseDouble((String) post.get("maxSalary")),
                            (String) post.get("payType")
                    )
            );
            post.put("picture", FileHelper.fileURL + post.get("picture"));
            post.remove("minAgeRequest");
            post.remove("maxAgeRequest");
            post.remove("minSalary");
            post.remove("maxSalary");
            post.remove("payType");
        }
        return new MyPageInfo(new PageInfo<>(posts));
    }

    @Override
    public Set<String> getEduEnum() {
        List<String> eduList = Arrays.asList(postMapper.selectEnumOfEdu().split("[,']"));
        Set<String> eduSet = new HashSet<>(eduList);
        eduSet.remove("");
        eduSet.remove("enum(");
        eduSet.remove(")");
        return eduSet;
    }

    @Override
    public Map<String, Object> getPostInformation(Integer postId) throws PostException {
        Map<String, Object> postInformation = postMapper.selectPostInformation(postId);
        if (postInformation == null) {
            throw new NullPostInformationException();
        } else {
            return postInformation;
        }
    }

    @Override
    public Map<String, Object> getPostIndex(Integer postId) throws PostException {
        Map<String, Object> postIndex = postMapper.selectPostIndex(postId);
        if (postIndex == null) {
            throw new NullPostIndexException();
        } else {
            return postIndex;
        }
    }

    @Override
    public void releasePost(
            Integer positionId,
            Integer requirePopulation,
            String contact,
            String address,
            double baseSalary,
            double maxSalary,
            double minSalary,
            Integer paySalaryDate,
            String payType,
            String salaryOtherNotice,
            String liveNotice,
            String foodNotice,
            String socialSecurityNotice,
            String liveFoodOtherNotice,
            String jobText,
            String jobTimeNotice,
            String jobWay,
            String jobOtherNotice,
            Boolean sexRequest,
            Integer maxAgeRequest,
            Integer minAgeRequest,
            String eduBackground,
            Integer minExpRequest,
            Integer maxExpRequest,
            String credentialRequest,
            String employOtherNotice
    ) {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        Map<String, Object> company = postMapper.selectCompanyByUsername(user.getUsername());
        String state = "待审核";
        Integer companyId = (Integer) company.get("companyId");
        String positionName = postMapper.selectPositionNameByPositionId(positionId);
        String postName = company.get("companyName") + "-" + positionName;
        postMapper.insertPostInformation(
                companyId,
                positionId,
                requirePopulation,
                contact,
                address,
                baseSalary,
                maxSalary,
                minSalary,
                paySalaryDate,
                payType,
                salaryOtherNotice,
                liveNotice,
                foodNotice,
                socialSecurityNotice,
                liveFoodOtherNotice,
                jobText,
                jobTimeNotice,
                jobWay,
                jobOtherNotice,
                sexRequest,
                maxAgeRequest,
                minAgeRequest,
                eduBackground,
                minExpRequest,
                maxExpRequest,
                credentialRequest,
                employOtherNotice,
                postName,
                state
        );
        postCache.clear();
    }

    @Override
    public Map<String, Object> getPostTotalInformation(Integer postId) throws PostException {
        Map<String, Object> postTotalInformation = postMapper.selectPostTotalInformation(postId);
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        String usn = user.getUsername();
        clickMapper.insertUserClickPost(usn,postId);
        if (postTotalInformation == null) {
            throw new PostNotExistException();
        } else {
            postTotalInformation.put("expRequest", yearDealer(
                    (Integer) postTotalInformation.get("minExpRequest"),
                    (Integer) postTotalInformation.get("maxExpRequest")
            ));
            postTotalInformation.remove("minExpRequest");
            postTotalInformation.remove("maxExpRequest");
            postTotalInformation.put("sexRequest", sexDealer((Boolean) postTotalInformation.get("sex")));
            postTotalInformation.remove("sex");
            return postTotalInformation;
        }
    }

    @Override
    public void editPost(
            Integer postId,
            Integer positionId,
            Integer requirePopulation,
            String contact,
            String address,
            double baseSalary,
            double maxSalary,
            double minSalary,
            Integer paySalaryDate,
            String payType,
            String salaryOtherNotice,
            String liveNotice,
            String foodNotice,
            String socialSecurityNotice,
            String liveFoodOtherNotice,
            String jobText,
            String jobTimeNotice,
            String jobWay,
            String jobOtherNotice,
            Boolean sexRequest,
            Integer maxAgeRequest,
            Integer minAgeRequest,
            String eduBackground,
            Integer minExpRequest,
            Integer maxExpRequest,
            String credentialRequest,
            String employOtherNotice
    ) {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        Map<String, Object> company = postMapper.selectCompanyByUsername(user.getUsername());
        String positionName = postMapper.selectPositionNameByPositionId(positionId);
        String postName = company.get("companyName") + "-" + positionName;
        postMapper.updatePost(
                postId,
                positionId,
                requirePopulation,
                contact,
                address,
                baseSalary,
                maxSalary,
                minSalary,
                paySalaryDate,
                payType,
                salaryOtherNotice,
                liveNotice,
                foodNotice,
                socialSecurityNotice,
                liveFoodOtherNotice,
                jobText,
                jobTimeNotice,
                jobWay,
                jobOtherNotice,
                sexRequest,
                maxAgeRequest,
                minAgeRequest,
                eduBackground,
                minExpRequest,
                maxExpRequest,
                credentialRequest,
                employOtherNotice,
                postName
        );
        postCache.clear();
    }

    @Override
    public void savePost(Map<String, Object> map) {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        postCache.put(user.getUsername(), map);
    }

    @Override
    public Map<String, Object> getSavedPost() throws PostException {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        Map<String, Object> map = postCache.get(user.getUsername());
        if (map == null) {
            throw new NullPostSavedException();
        } else {
            return map;
        }
    }

    @Override
    public Map<String, Object> getRecentEditorPost() throws PostException {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        List<Map<String, Object>> recentEditorPost = postMapper.selectRecentEditorPost(user.getUsername());
        if (recentEditorPost.size() == 0) {
            throw new NullRecentEditorPost();
        } else {
            for (Map<String, Object> stringObjectMap : recentEditorPost) {
                if (stringObjectMap.get("state").equals("已发布")) {
                    stringObjectMap.put("state", String.valueOf(stringObjectMap.get("releaseTime")));
                }
                stringObjectMap.remove("releaseTime");
            }
            return recentEditorPost.get(0);
        }
    }

    @Override
    public void aduitPost(Integer postId) throws PostException {
        Post post = postMapper.selectPost(postId);
        if (post == null || !post.getState().equals("待审核")) {
            throw new PostNotExistException();
        } else {
            postMapper.updatePostStateRelease(postId);
        }
    }

    @Override
    public void rejectPost(Integer postId) throws PostException {
        Post post = postMapper.selectPost(postId);
        if (post == null || !post.getState().equals("待审核")) {
            throw new PostNotExistException();
        } else {
            postMapper.updatePostStateReject(postId);
        }
    }

    /**
     * 处理年限要求
     *
     * @param min 最低
     * @param max 最高
     * @return 要求字符串
     */
    private String yearDealer(Integer min, Integer max) {
        if (min == 0 && max == 0)
            return "不限";
        else if (min.equals(max))
            return min + "年";
        else if (min > max)
            return min + "年以上";
        else if (min.equals(0))
            return max + "年以下";
        else
            return min + "到" + max + "年";
    }

    /**
     * 处理年限要求
     *
     * @param min 最低
     * @param max 最高
     * @return 要求字符串
     */
    private String yearDealerFault(Integer min, Integer max) {
        if (min == 0 && max == 0)
            return "不限";
        else if (min.equals(max))
            return min + "岁";
        else if (min > max)
            return min + "岁以上";
        else if (min.equals(0))
            return max + "岁以下";
        else
            return min + "到" + max + "岁";
    }

    /**
     * 处理工资介绍
     *
     * @param min  最小工资
     * @param max  最大工资
     * @param time 发薪时间单位
     * @return 工资介绍字符串，如（xxx-yyy/zzz）
     */
    private String salaryDealer(Double min, Double max, String time) {
        return min.intValue() + "-" + max.intValue() + "/" + time;
    }

    @Override
    public MyPageInfo getPostGeneral(String state, String name, Integer pageNo, Integer pageSize)
            throws PostGeneralException {
        PageHelper.startPage(pageNo, pageSize);
        String name1 = SearchKeyUtil.makeKey(name);
        String state1 = SearchKeyUtil.makeKey(state);
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();

        List<Map<String, Object>> x = postMapper.selectPostGeneral(name1, state1, user.getUsername());
        if (x.size() == 0)
            throw new NoPostException();

        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(x);
        for (Map<String, Object> temp : pageInfo.getList()) {
            if (temp.get("publishTime") == null)
                temp.put("publishTime", null);
            else
                temp.replace("publishTime", temp.get("publishTime").toString());
        }
        return new MyPageInfo(pageInfo);
    }

    @Override
    public List<Map<String, Object>> getPostCondition(Integer postId) throws PostConditionException {
        List<Map<String, Object>> x = postMapper.SelectPostCondition(postId);
        if (x.size() == 0)
            throw new NoPostConditionException();
        for (Map<String, Object> temp : x) {
            temp.replace("date", temp.get("date").toString());
        }
        return x;
    }

    @Override
    public Integer getPostNewEnroll() {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        Map<String, Object> x = postMapper.SelectLastTime(user.getUsername());
        Date date = new Date();

        Timestamp time = new Timestamp(date.getTime());
        Timestamp lastTime = time;
        if (x != null) {
            lastTime = (Timestamp) x.get("last_login_time");
        }
        if (postMapper.SelectNewPost(time, user.getUsername()) == null)
            return 0;
        return postMapper.SelectNewPost(time, user.getUsername()).size() -
                postMapper.SelectNewPost(lastTime, user.getUsername()).size();
    }

    @Override
    public String underCarriage(Integer id) {
        Integer x = postMapper.updateStateOfPost(id);
        String a;
        if (x == 1)
            a = "已下架此招聘";
        else
            a = "请勿重复下架";
        return a;
    }

    @Override
    public String deletePost(List<Integer> idList) {
        String a;
        for (Integer id : idList) {
            Integer x = postMapper.deletePost(id);
        }
        a = "招聘删除成功";
        return a;
    }

    @Override
    public List<Map<String, Object>> getPosition(Integer id) throws PositionGetException {
        List<Map<String, Object>> x = postMapper.getPosition(id);
        if (x.size() == 0)
            throw new NoPositionException();
        return x;
    }

    /**
     * 处理性别要求
     *
     * @param sex 性别要求
     * @return 性别要求
     */
    private String sexDealer(Boolean sex) {
        if (sex == null) {
            return "不限";
        } else {
            if (sex) {
                return "男";
            } else {
                return "女";
            }
        }
    }

    /**
     * 岗位缓存
     */
    private static Cache<String, Map<String, Object>> postCache;

    static {
        //初始化缓存
        //缓存管理器
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:Post-ehcache-setting.xml");
        postCache = cacheManager.getCache("postCache");
    }

    @Override
    public MyPageInfo getAdminPostGeneral(Integer professionId, String name, Integer pageNo, Integer pageSize)
            throws PostGeneralException {
        PageHelper.startPage(pageNo, pageSize);
        String name1 = SearchKeyUtil.makeKey(name);
        List<Map<String, Object>> x = new ArrayList<Map<String, Object>>();
        if (professionId == null) {
            x = postMapper.selectAdminPostGeneral2(name1);
        } else {
            x = postMapper.selectAdminPostGeneral1(name1, professionId);
        }
        if (x.size() == 0)
            throw new NoPostException();

        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(x);
        for (Map<String, Object> temp : pageInfo.getList()) {
            if (temp.get("publishTime") == null)
                temp.put("publishTime", null);
            else
                temp.replace("publishTime", temp.get("publishTime").toString());
        }
        return new MyPageInfo(pageInfo);
    }

    @Override
    public Integer getAdminPostEnrollCount(Integer postId) {
        Integer x = postMapper.selectAdminPostEnrollCount(postId);
        if (x == null) {
            x = 0;
        }
        return x;
    }

}
